/*
实验15-5 代金券
分数 30
作者 陈越
单位 浙江大学

设购物车里有 n 种商品，而你手里有 n 种代金券，可以在购买任何一种商品的时候获得抵扣优惠。同时，你手里有 d 元钱，怎么能买到最大数量的商品？

每种代金券可以多次使用，每种商品也可以购买多次，但是一种代金券只能在购买一种商品时用一次。例如代金券 1 可以用在商品 1 上，然后还可以用代金券 2 继续购买商品 1；同时代金券 1 还可以用在商品 2 上，但代金券 1 不可以再次用于购买商品 1。

举个具体的例子：假设有 4 种商品，价格分别为 10 元、12 元、15 元、20 元。另有 4 种优惠券，可以分别抵扣 6 元、7 元、8 元、9 元。如果你手头有 30 元，则一种最佳购买方案是：

    用 4 种代金券分别购买 10 元的商品各 1 次，付出 40−6−7−8−9=10（元）；
    购买 12 元的商品 3 次，分别用掉面值最大的 3 种代金券，付出 36−7−8−9=12（元）；
    购买 15 元的商品 1 次，用掉 9 元代金券，付出 15−9=6（元）。

如此你手中最后剩下 2 元，不够买任何商品了。而你获得了最多 8 件商品。
输入格式：

输入首先在一行中给出两个正整数：n（≤105），即商品种类数（同时也是代金券种类数）；d（≤106），即你手中的现金量（以元为单位）。

随后第二行给出 n 种商品的价格；第三行给出 n 种代金券的抵扣价。均为不超过 109 的正整数，且保证代金券的最高抵扣价小于最低的商品价格。同行数字间以空格分隔。
输出格式：

在一行中输出两个数字，依次为可以购买的商品的最大数量、剩余现金的最大值，其间以 1 个空格分隔。
输入样例：

4 30
12 20 15 10
9 6 8 7

输出样例：

8 2
*/

/*
要解决这个问题，我们需要在给定的现金限制下，使用代金券尽可能多地购买商品，并确保剩余现金最多。关键在于贪心算法的应用，通过优先选择每次购买的最小花费来最大化购买数量。
方法思路

    排序代金券：将代金券按抵扣金额从大到小排序，以便优先使用抵扣最多的代金券。

    最小堆维护当前最优选择：使用最小堆来动态维护当前所有可能的购买选项中的最小花费。

    贪心选择：每次从堆中取出最小花费进行购买，并更新剩余金额和购买次数。若还能继续购买该商品的下一次（使用下一个代金券），则将新的花费加入堆中。
*/

#include <iostream>
#include <queue>
#include <vector>
#include <algorithm>
#include <utility>

// 自定义比较函数，用于实现最小堆
struct Compare {
    bool operator()(const std::tuple<int, int, int>& a, const std::tuple<int, int, int>& b) {
        return std::get<0>(a) > std::get<0>(b);
    }
};

int main() {
    int n, d;
    std::cin >> n >> d;

    std::vector<int> prices(n);
    std::vector<int> coupons(n);

    for (int i = 0; i < n; ++i) {
        std::cin >> prices[i];
    }

    for (int i = 0; i < n; ++i) {
        std::cin >> coupons[i];
    }

    // 代金券排序：将代金券按抵扣金额从高到低排序，以便优先使用抵扣最多的券。
    std::sort(coupons.rbegin(), coupons.rend());

    // 使用优先队列实现最小堆
    std::priority_queue<std::tuple<int, int, int>, std::vector<std::tuple<int, int, int>>, Compare> heap;

    // 初始化堆：计算每个商品首次使用最高抵扣券的花费，并将这些花费加入最小堆。
    for (int price : prices) {
        if (!coupons.empty()) {
            int initial_cost = price - coupons[0];
            if (initial_cost <= d) {
                heap.push(std::make_tuple(initial_cost, price, 0));
            }
        }
    }

    int total_spent = 0;
    int count = 0;

    while (!heap.empty()) {
        // 循环从堆中取出最小花费
        auto [cost, price, k] = heap.top();
        heap.pop();

        if (total_spent + cost > d) {
            break;
        }

        // 累加总花费和购买次数
        total_spent += cost;
        count += 1;

        // 若还能继续使用下一个代金券购买当前商品，则将新的花费加入堆。
        int next_k = k + 1;
        if (next_k < coupons.size()) {
            int next_cost = price - coupons[next_k];
            heap.push(std::make_tuple(next_cost, price, next_k));
        }
    }

    // 结果输出：计算剩余金额并输出最大购买次数和剩余现金。
    int remaining = d - total_spent;
    std::cout << count << " " << remaining << std::endl;

    return 0;
}